﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Net.Mail;
using System.Globalization;
using System.Text;
using MLY.Dal;
using MLY.Bll;

namespace MLY
{
    public static class Utils
    {

        public static DateTime StrToDateTime(string dateString)
        {
            return DateTime.ParseExact(dateString, "dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);
        }

        public static DateTime MinSqlDateTime
        {
            get
            {
                return StrToDateTime("01/01/1753 12:00:00");
            }
        }

        public static DateTime MaxSqlDateTime
        {
            get
            {
                return StrToDateTime("31/12/9999 23:59:59");
            }
        }

        public static string ShowDatetime(DateTime time)
        {
            string ReturnValue = "";
            if (time.Year >= 2010)
            {
                ReturnValue = time.Day.ToString() + "." + 
                              time.Month.ToString() + "." + 
                              time.Year.ToString() + " " +
                              Get2digitsNumber(time.Hour) + ":" + 
                              Get2digitsNumber(time.Minute);                  
            }
            return ReturnValue;
        }

        private static string Get2digitsNumber(int num)
        {
            if ((num >= 10) || (num < 0))
                return num.ToString();
            return "0" + num.ToString();
        }

        public static string GetIP()
        {
            try
            {
                HttpRequest currentRequest = HttpContext.Current.Request;
                string ipAddress = currentRequest.ServerVariables["HTTP_X_FORWARDED_FOR"];

                if (ipAddress == null || ipAddress.ToLower() == "unknown")
                    ipAddress = currentRequest.ServerVariables["REMOTE_ADDR"];

                return ipAddress;
            }
            catch
            {
                return "";
            }
        }

        public static bool IsSqlDate(DateTime dateTime)
        {
            return dateTime >= Utils.MinSqlDateTime && dateTime <= Utils.MaxSqlDateTime;
        }

        public static bool IsSqlDate(DateTime? dateTime)
        {
            return dateTime.HasValue && IsSqlDate(dateTime.Value);
        }

        public static bool IsDebug
        {
            get
            {
                object isDebug = ConfigurationManager.AppSettings["debug"];
                bool result = SameText(isDebug.ToString(), "true");
                return result;
            }
        }

        public static bool SameText(string a, string b)
        {
            if (a == null && b == null)
                return true;
            if (a == null || b == null)
                return false;

            return a.Equals(b, StringComparison.OrdinalIgnoreCase);
        }

        public static string AppSettings(string key)
        {
            return System.Configuration.ConfigurationManager.AppSettings[key];
        }

        public static void SendPendingAlerts()
        {
            using (SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MLYConnectionString"].ConnectionString))
            {
                SqlCommand cmd = new SqlCommand("AlertSendPendingMails", conn);
                cmd.CommandType = CommandType.StoredProcedure;
                string Address, Subject, Body;
                SqlDataReader reader;
                try
                {
                    conn.Open();
                    reader = cmd.ExecuteReader();
                    if (reader.HasRows)
                        while (reader.Read())
                        {
                            Address = reader.GetString(0);
                            Subject = reader.GetString(1);
                            Body = reader.GetString(2);
                            mlySendMail(Subject, Address, "", "yoav@mly.co.il", Body, false, null);
                            // copy to Shaul:
                            mlySendMail("Copy of " + Subject, "pastch@gmail.com", "", "", Body, false, null);
                        }
                        
                }
                catch (Exception ex) 
                {
                    Log.WriteError("Alert mail send had failed with error", ex);
                }
                finally
                {
                    conn.Close();
                }
            }
        }

        public static void CheckAlerts()
        {
            using (SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MLYConnectionString"].ConnectionString))
            {
                SqlCommand cmd = new SqlCommand("Alert_InsertUpdateCheck", conn);
                cmd.CommandType = CommandType.StoredProcedure;
                
                try
                {
                    conn.Open();
                    cmd.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    Log.WriteError("Alert_InsertUpdateCheck had failed with error", ex);
                }
                finally
                {
                    conn.Close();
                }
            }
        }

        public static DateTime CanceledDate { get { return new DateTime(2099, 1, 1); } }

        public static string GetPreviousLogin()
        {
            string ReturnValue = "";
            DateTime LoginDate;
            
            using (Dal.lqKbmDataContext dc = new MLY.Dal.lqKbmDataContext())
            {
                try
                {
                    LoginDate = (from l in dc.TableUserLogins
                                 where l.UserId == currUserId
                                 orderby l.LoginDate descending
                                 select l.LoginDate).FirstOrDefault();
                    if (LoginDate.Year > 2010)
                    {
                        LoginDate = (from l in dc.TableUserLogins
                                     where l.UserId == currUserId &&
                                           l.LoginDate < LoginDate
                                     orderby l.LoginDate descending
                                     select l.LoginDate).FirstOrDefault();
                    }
                    ReturnValue = ShowDatetime(LoginDate);
                }
                catch (Exception ex) 
                {
                    Log.WriteError("GetPreviousLogin had failed with error", ex);
                }
            }

            return ReturnValue;
        }
        
        public static int currUserId
        {
            get
            {
                return HttpContext.Current.Session["UserId"] == null ? -1 : Convert.ToInt32(HttpContext.Current.Session["UserId"]);
            }
            set
            {
                HttpContext.Current.Session["UserId"] = value;
            }
        }

        public static clsUser currUser
        {
            get
            {
                return new clsUser(currUserId);
            }

        }


        // removed, as it was redundant and buggy. Using session parameters instead.
        //public static clsOrganization currOrg
        //{
        //    get
        //    {
        //        return new clsOrganization(currUserId.ToString());
        //    }
        //}

        public static string[] FORMATS = {  @"d/M/yyyy", 
                                        @"d/M/yy", 
                                        @"dd/MM/yyyy", 
                                        @"dd/MM/yyyy hh:mm:ss", 
                                        @"dd/MM/yy", 
                                        @"dd-MM-yyyy",
                                        @"dd-MM-yy" };

        public static void AttachClicked(object sender, ImageClickEventArgs e)
        {
            string woNumber = ((ImageButton)sender).CommandArgument;
            string script = String.Format(@"<script language ='javascript'>window.open('AttachmentManager.aspx?woId={0}','width=200, height=77')</script>", woNumber);
            if (HttpContext.Current.Handler is Page)
                ((Page)HttpContext.Current.Handler).ClientScript.RegisterStartupScript(((Page)HttpContext.Current.Handler).GetType(), "myScript", script);
        }

        public static DateTime dateParseString(string x)
        {
            DateTime tmpDate;
            try
            {
                DateTime.TryParseExact(x, FORMATS, null, DateTimeStyles.None, out tmpDate);
            }
            catch
            {
                throw new Exception("unable to Parse Date");
            }
            return tmpDate;
        }

        static string[] defaultCsvTemplate
        {
            get
            {
                using (Dal.lqKbmDataContext dc = new MLY.Dal.lqKbmDataContext())
                {
                    return dc.Lookup_CsvFields.Select(S => S.CsvField_Name).ToArray<string>();
                }
            }
        }

        static string default_Encoding = "windows-1255";

        public static System.Text.Encoding currEncoding
        {
            get
            {
                Dal.lqKbmDataContext context = new MLY.Dal.lqKbmDataContext();
                Dal.TableUser usr = context.TableUsers.Where(S => S.UserId == currUserId).FirstOrDefault();
                if (usr.EncodingId != null)
                    return Encoding.GetEncoding(context.Lookup_Encodings.Where(S => S.Idx == usr.EncodingId).Select(Q => Q.Encoding_Name).FirstOrDefault());
                else
                    return Encoding.GetEncoding(default_Encoding);
            }
        }

        //public static List<Dict.Dict> dicts
        //{
        //  get
        //  {
        //    return HttpContext.Current.Session["dict"] == null ? null : (List<Dict.Dict>)HttpContext.Current.Session["dict"];
        //  }
        //  set
        //  {
        //    HttpContext.Current.Session["dict"] = value;
        //  }
        //}

        public static string[] csvPaths
        {
            get
            {
                clsCsvTemplate c = new clsCsvTemplate(currUserId);

                if (c.count() == 0)
                    return defaultCsvTemplate;
                else
                    return c.toStringArray();
            }
        }

        public enum MailTemplate
        {
            AddContractor = 1
        }

        public static String AdminMail
        {
            get
            {
                return ConfigurationManager.AppSettings["AdminMail"];
            }
        }

        /// <summary>
        /// SEPERATE MULTIPLE ADDRESSS WITH ','
        /// </summary>
        /// <param name="in_subject"></param>
        /// <param name="in_to"></param>
        /// <param name="in_cc"></param>
        /// <param name="in_bcc"></param>
        /// <param name="content"></param>
        public static void mlySendMail(string in_subject, string in_to, string in_cc, string in_bcc, string content, bool copyAdmin, MailTemplate? template)
        {
            try
            {
                MailMessage mailMessage = new MailMessage();
                mailMessage.Body = template.HasValue ? new ClsMailTemplate(template.Value).getHtmlWithContent(content) : content;

                if (!String.IsNullOrEmpty(in_to))
                    mailMessage.To.Add(in_to);
                if (copyAdmin)
                    mailMessage.To.Add(AdminMail);
                if (in_cc != "")
                    mailMessage.CC.Add(in_cc);
                if (in_bcc != "")
                    mailMessage.Bcc.Add(in_bcc);
                
                mailMessage.IsBodyHtml = true;
                
                mailMessage.Subject = in_subject;
                mailMessage.Priority = MailPriority.Low;

                System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient();
                client.EnableSsl = true;
                client.Send(mailMessage);
                Log.WriteInfo(string.Format(@"Mail was successfully sent: 
                  to: {0}
                  from: {1}
                  CC: {2}
                  BCC: {3}
                  subject: {4}
                  body: {5}", mailMessage.To, mailMessage.From, mailMessage.CC, mailMessage.Bcc, mailMessage.Subject, mailMessage.Body));
                //ClsMailTemplate mt = new ClsMailTemplate();
            }
            catch (Exception exception)
            {
                Log.WriteError("Mail send had failed with error", exception);
            }
        }

        public static int _orgId
        {
            get
            {
                return HttpContext.Current.Session["OrganizationId"] == null ? -1 : (int)HttpContext.Current.Session["OrganizationId"];
            }
            set
            {
                HttpContext.Current.Session["OrganizationId"] = value;
            }
        }

        public static DateTime? ParseDate(string s)
        {
            try
            {
                if (String.IsNullOrEmpty(s))
                    return null;
                lqKbmDataContext dc = new lqKbmDataContext();
                TableUser currUser = dc.TableUsers.Where(S => S.UserId == currUserId).FirstOrDefault();
                if (String.IsNullOrEmpty(currUser.DefaultDateFormat))
                    return DateTime.ParseExact(s, FORMATS, CultureInfo.InvariantCulture, DateTimeStyles.None);
                else
                    return DateTime.ParseExact(s, currUser.DefaultDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None);
            }
            catch (Exception exception)
            {
                Log.WriteError(string.Format("Failed to parse {0} as date.", s), exception);
                return null;
            }
        }

        public static string FormatDateToSql(DateTime? date)
        {
            if (date == null)
                return "IS NULL";
            else
                return string.Format("CONVERT(DATETIME, '{0:yyyy-MM-dd HH:mm:ss}', 102)", date); //2013-02-28 14:55:00'
        }

        public static string SqlDate(DateTime date)
        {
            return date.Year + "-" + date.Month + "-" + date.Day + " " + formatHourMinute(date.Hour) + ":" + formatHourMinute(date.Minute);
        }

        private static string formatHourMinute(int data)
        {
            if (data < 10)
                return ("0" + data.ToString());
            return data.ToString();
        }

        public static string getAppConfigString(string s)
        {
            return ConfigurationManager.AppSettings[s];
        }

        public static void logOff()
        {
            HttpContext.Current.Session.Clear();
            HttpContext.Current.Response.RedirectTo("/LTR/Login.aspx", true);
        }

        public static DateTime EndOfTheDay(DateTime d)
        {
            return d.Date.AddDays(1).AddSeconds(-1);
        }

        public static DateTime MaxDate(DateTime a, DateTime b)
        {
            if (a > b)
                return a;
            else
                return b;
        }

        private static int TranslateWorkDaysToNormalDays(int Days)
        {
            int NormalDays = 0;
            DateTime Now = DateTime.Now;
            int WeekDay = (int)Now.DayOfWeek;
            if (WeekDay == 6)
            {
                Now = Now.AddDays(-1);
                WeekDay = 5;
            }
            if (WeekDay == 7)
            {
                Now = Now.AddDays(-2);
                WeekDay = 5;
            }

            while (Days > 5)
            {
                Days -= 5;
                NormalDays += 7;
            }
            NormalDays += Days;
            if (Days > WeekDay)
                NormalDays += 2;

            return NormalDays;
        }

        public static DateTime DateXWorkDaysAgo(int X)
        {
            DateTime Date;
            X = TranslateWorkDaysToNormalDays(X);

            Date = DateTime.Now.AddDays(-X);

            // setting the date to be at midnight at the beginning of the day
            Date = Date.AddHours(-Date.Hour);
            Date = Date.AddMinutes(-Date.Minute);
            Date = Date.AddSeconds(-Date.Second);
            Date = Date.AddMilliseconds(-Date.Millisecond);

            // removing one more second = a workaround
            Date = Date.AddSeconds(-1);

            return (Date);
        }

        public static int TranslateNormalDaysToWorkDays(int days)
        {
            if (days < 0)
                return -1;

            int WorkDays = 0;
            DateTime Now = DateTime.Now;
            int WeekDay = (int)Now.DayOfWeek;
            if (WeekDay == 6)
            {
                WeekDay = 1;
                Now.AddDays(2);
                days -= 2;
            }
            if (WeekDay == 7)
            {
                WeekDay = 1;
                Now.AddDays(1);
                days -= 1;
            }

            while (days >= 7)
            {
                WorkDays += 5;
                days -= 7;
            }
            WorkDays += days;

            return WorkDays;
        }
    }
}
